#pragma once

#include <vex/core/config.h>
#include <vex/core/make_raw_handle.h>
#include <vex/functional/contract/invokable_signal.h>
#include <vex/functional/implementation/default_value.h>
#include <boost/function_types/result_type.hpp>

//namespace vex { namespace functional { namespace implementation {
//
//    namespace bft = boost::function_types;
//
//    template< 
//        class TSignature,
//        class TSignalTraits,
//        class TSignalContract = contract::invokable_signal<TSignature> 
//    >
//    class invokable_signal_default_impl;
//
//    namespace detail {
//        template<class TSignature, class TSignalTraits, class TSignalContract>
//        class VEX_ABSTRACT invokable_signal_default_impl_base : public TSignalContract {
//            invokable_signal_default_impl_base(invokable_signal_default_impl_base const&);
//            invokable_signal_default_impl_base& operator=(invokable_signal_default_impl_base const&);
//        protected:
//            typedef TSignalTraits signal_traits;
//            typedef typename TSignalContract::delegate_type delegate_type;
//            typedef typename signal_traits::signal_type signal_type;
//            typedef typename default_value<TSignature> default_value_type;
//
//            signal_type m_signal;
//            default_value_type m_default;
//
//            invokable_signal_default_impl_base(default_value_type&& p_default) 
//                : m_default(std::move(p_default)) {}
//
//            invokable_signal_default_impl_base(invokable_signal_default_impl_base&& p_other)
//                : m_signal(std::move(p_other.m_signal))
//                , m_default(std::move(p_other.m_default)) {}
//        public:
//            // implements connect
//            virtual contract::connection* connect(
//                delegate_type* p_delegate, 
//                connection_required::domain p_conn_req = connection_required::no)
//            {
//                return signal_traits::connect(this->m_signal, p_delegate, p_conn_req);
//            }
//        };
//    }
//
//#define VEX_INVOKABLE_SIGNAL_IMPL_BODY \
//    typedef typename base_type::signal_traits signal_traits; \
//    typedef typename base_type::delegate_type delegate_type; \
//    typedef typename base_type::signal_type signal_type; \
//    typedef typename base_type::default_value_type default_value_type; \
//    \
//    invokable_signal_default_impl(default_value_type&& p_default = default_value_type()) \
//        : base_type(std::move(p_default)) {} \
//    invokable_signal_default_impl(invokable_signal_default_impl&& p_other) \
//        : base_type(std::move(p_other)) {}
//
//    template<
//        class TRet, 
//        class TSignalTraits, 
//        class TSignalContract
//    >
//    class VEX_ABSTRACT invokable_signal_default_impl<
//        TRet (), 
//        TSignalTraits, 
//        TSignalContract
//    > : public detail::invokable_signal_default_impl_base<
//        TRet (), 
//        TSignalTraits, 
//        TSignalContract
//    >
//    {
//    protected:
//        typedef detail::invokable_signal_default_impl_base<
//            TRet (), 
//            TSignalTraits, 
//            TSignalContract
//        > base_type;
//
//        VEX_INVOKABLE_SIGNAL_IMPL_BODY;
//    public:
//        virtual TRet invoke() const
//        {
//            return signal_traits::invoke_all(this->m_default, this->m_signal);
//        }
//    };
//
//    template<
//        class TRet, 
//        class TArg1, 
//        class TSignalTraits, 
//        class TSignalContract
//    >
//    class VEX_ABSTRACT invokable_signal_default_impl<
//        TRet (TArg1), 
//        TSignalTraits, 
//        TSignalContract
//    > : public detail::invokable_signal_default_impl_base<
//        TRet (TArg1), 
//        TSignalTraits, 
//        TSignalContract
//    >
//    {
//    protected:
//        typedef detail::invokable_signal_default_impl_base<
//            TRet (TArg1), 
//            TSignalTraits, 
//            TSignalContract
//        > base_type;
//
//        VEX_INVOKABLE_SIGNAL_IMPL_BODY;
//    public:
//        virtual TRet invoke(TArg1 p_arg) const
//        {
//            return signal_traits::invoke_all(this->m_default, this->m_signal,
//                std::forward<TArg1>(p_arg));
//        }
//    };
//
//    template<
//        class TRet, 
//        class TArg1, class TArg2, 
//        class TSignalTraits, 
//        class TSignalContract
//    >
//    class VEX_ABSTRACT invokable_signal_default_impl<
//        TRet (TArg1, TArg2), 
//        TSignalTraits, 
//        TSignalContract
//    > : public detail::invokable_signal_default_impl_base<
//        TRet (TArg1, TArg2), 
//        TSignalTraits,
//        TSignalContract
//    >
//    {
//    protected:
//        typedef detail::invokable_signal_default_impl_base<
//            TRet (TArg1, TArg2), 
//            TSignalTraits, 
//            TSignalContract
//        > base_type;
//
//        VEX_INVOKABLE_SIGNAL_IMPL_BODY;
//    public:
//        virtual TRet invoke(TArg1 p_arg1, TArg2 p_arg2) const
//        {
//           return signal_traits::invoke_all(this->m_default, this->m_signal,
//               std::forward<TArg1>(p_arg1), 
//               std::forward<TArg2>(p_arg2));
//        }
//    };
//
//    template<
//        class TRet, 
//        class TArg1, class TArg2, class TArg3, 
//        class TSignalTraits, 
//        class TSignalContract
//    >
//    class VEX_ABSTRACT invokable_signal_default_impl<
//        TRet (TArg1, TArg2, TArg3), 
//        TSignalTraits, 
//        TSignalContract
//    > : public detail::invokable_signal_default_impl_base<
//        TRet (TArg1, TArg2, TArg3), 
//        TSignalTraits, 
//        TSignalContract
//    >
//    {
//    protected:
//        typedef detail::invokable_signal_default_impl_base<
//            TRet (TArg1, TArg2, TArg3), 
//            TSignalTraits,
//            TSignalContract
//        > base_type;
//
//        VEX_INVOKABLE_SIGNAL_IMPL_BODY;
//    public:
//        virtual TRet invoke(TArg1 p_arg1, TArg2 p_arg2, TArg3 p_arg3) const
//        {
//            return signal_traits::invoke_all(this->m_default, this->m_signal,
//                std::forward<TArg1>(p_arg1), 
//                std::forward<TArg2>(p_arg2),
//                std::forward<TArg3>(p_arg3));
//        }
//    };
//
//    template<
//        class TRet, 
//        class TArg1, class TArg2, class TArg3, class TArg4, 
//        class TSignalTraits, 
//        class TSignalContract
//    >
//    class VEX_ABSTRACT invokable_signal_default_impl<
//        TRet (TArg1, TArg2, TArg3, TArg4), 
//        TSignalTraits, 
//        TSignalContract
//    > : public detail::invokable_signal_default_impl_base<
//        TRet (TArg1, TArg2, TArg3, TArg4), 
//        TSignalTraits, 
//        TSignalContract
//    >
//    {
//    protected:
//        typedef detail::invokable_signal_default_impl_base<
//            TRet (TArg1, TArg2, TArg3, TArg4), 
//            TSignalTraits,
//            TSignalContract
//        > base_type;
//
//        VEX_INVOKABLE_SIGNAL_IMPL_BODY;
//    public:
//        virtual TRet invoke(TArg1 p_arg1, TArg2 p_arg2, TArg3 p_arg3, TArg4 p_arg4) const
//        {
//            return signal_traits::invoke_all(this->m_default, this->m_signal,
//                std::forward<TArg1>(p_arg1), 
//                std::forward<TArg2>(p_arg2),
//                std::forward<TArg3>(p_arg3),
//                std::forward<TArg4>(p_arg4));
//        }
//    };
//
//    template<
//        class TRet, 
//        class TArg1, class TArg2, class TArg3, class TArg4, class TArg5, 
//        class TSignalTraits,
//        class TSignalContract>
//    class VEX_ABSTRACT invokable_signal_default_impl<
//        TRet (TArg1, TArg2, TArg3, TArg4, TArg5), 
//        TSignalTraits,
//        TSignalContract
//    > : public detail::invokable_signal_default_impl_base<
//        TRet (TArg1, TArg2, TArg3, TArg4, TArg5), 
//        TSignalTraits,
//        TSignalContract
//    >
//    {
//    protected:
//        typedef detail::invokable_signal_default_impl_base<
//            TRet (TArg1, TArg2, TArg3, TArg4, TArg5), 
//            TSignalTraits,
//            TSignalContract
//        > base_type;
//
//        VEX_INVOKABLE_SIGNAL_IMPL_BODY;
//    public:
//        virtual TRet invoke(TArg1 p_arg1, TArg2 p_arg2, TArg3 p_arg3, TArg4 p_arg4, TArg5 p_arg5) const
//        {
//            return signal_traits::invoke_all(this->m_default, this->m_signal,
//                std::forward<TArg1>(p_arg1), 
//                std::forward<TArg2>(p_arg2),
//                std::forward<TArg3>(p_arg3),
//                std::forward<TArg4>(p_arg4),
//                std::forward<TArg5>(p_arg5));
//        }
//    };
//}}}